package com.witker.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 类型转换工具
 * Created by BOCAI on 2018/9/16 19:30.
 */
public class ClassTypeUtil {

    /**
     * 日志管理器
     */
    private static Logger LOG = LoggerFactory.getLogger(ClassTypeUtil.class);

    private ClassTypeUtil() {
    }

    /**
     * 将指定的对象转换成String类型
     * @param data 将被转换的对象
     * @return 转换成功返回String类型的数据，否则返回Null
     */
    public static String toString(Object data) {
        String result = NoneTypeUtil.STRING;

        if (data != null){
            result = String.valueOf(data);
        }

        return result;
    }

    /**
     * 把使用Base64编码技术将文件字节转换为字符串
     * @param bytes 文件字节
     * @return 转换成功返回字符串
     */
    public static String toString(byte[] bytes) {
        return new BASE64Encoder().encode(bytes);
    }

    /**
     * 将指定的对象转换成整数
     * @param data 将被转换的对象
     * @return 转换成功返回整数类型的数据，否则返回NoneType.INTEGER
     */
    public static int toInt(Object data) {
        int result = NoneTypeUtil.INTEGER;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)){
                result = Integer.parseInt(temp);
            }

        } catch (Exception ex) {
            LOG.error("ClassTypeUtil.toInt(Object data)报错,可能包含非数字字符",ex);
        }
        return result;
    }

    /**
     * 将指定的对象转换成Long类型数据
     * @param data 将被转换的对象
     * @return 转换成功返回Long类型的数据，否则返回NoneType.LONG
     */
    public static long toLong(Object data) {
        long result = NoneTypeUtil.LONG;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)){
                result = Long.parseLong(temp);
            }

        } catch (Exception e) {
            LOG.error("ClassTypeUtil.toLong(Object data)报错,可能包含非数字字符", e);
        }
        return result;
    }

    /**
     * 将指定的对象转换成byte类型数据
     * @param data 将被转换的对象
     * @return 转换成功返回byte类型数据，否则返回NoneType.BYTE
     */
    public static byte toByte(Object data) {
        byte result = NoneTypeUtil.BYTE;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)){
                result = Byte.parseByte(temp);
            }

        } catch (Exception e) {
            LOG.error("ClassTypeUtil.toByte(Object data)报错,可能包含非0或非1的字符", e);
        }
        return result;
    }

    /**
     * 将指定的对象转换成byte[]类型数据
     * @param data 将被转换的对象
     * @return 转换成功返回byte[]类型数据，否则返回Null
     */
    public static byte[] toBytes(Object data) {
        byte[] result = null;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)) {
                result = temp.getBytes();
            }

        } catch (Exception e) {
            LOG.error("错误", e);
        }
        return result;
    }

    /**
     * 使用Base64编码技术把文件的字符串解码为字节
     * @param fileString 文件的字符串
     * @return 转换成功返回byte[]类型数据，否则返回Null
     */
    public static byte[] toBytes(String fileString) {
        byte[] result = null;

        try {
            result = new BASE64Decoder().decodeBuffer(fileString);

        } catch (IOException e) {
            LOG.error("ClassTypeUtil.toBytes(String fileString)报错,Base64解码发生错误", e);
        }
        return result;
    }

    /**
     * 将使用指定的编码将指定的对象转换成byte[]类型数据
     * @param data 将被转换的对象
     * @param encodingName 编码名称
     * @return 转换成功返回byte[]类型数据，否则返回Null
     */
    public static byte[] toBytes(Object data, String encodingName) {
        byte[] result = null;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)){
                result = temp.getBytes(encodingName);
            }

        } catch (Exception e) {
            LOG.error("ClassTypeUtil.toBytes(Object data, String encodingName)报错,不支持当前编码字符集", e);
        }
        return result;
    }

    /**
     * 将指定的对象转换成float类型的数据
     * @param data 将被转换的对象
     * @return 转换成功返回byte类型数据，否则返回NoneType.FLOAT
     */
    public static float toFloat(Object data) {
        float result = NoneTypeUtil.FLOAT;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)){
                result = Float.parseFloat(temp);
            }

        } catch (Exception e) {
            LOG.error("ClassTypeUtil.toFloat(Object data)报错,可能包含非数字字符", e);
        }
        return result;
    }

    /**
     * 将指定的对象转换成double类型的数据
     * @param data 将被转换的对象
     * @return 转换成功返回byte类型数据，否则返回NoneType.DOUBLE
     */
    public static double toDouble(Object data) {
        double result = NoneTypeUtil.DOUBLE;
        String temp = toString(data);

        try {
            if (!NoneTypeUtil.isNull(temp)){
                result = Double.parseDouble(temp);
            }

        } catch (Exception e) {
            LOG.error("ClassTypeUtil.toDouble(Object data)报错,可能包含非数字字符", e);
        }
        return result;
    }

    /**
     * 将指定的对象转换成BigDecimal类型的数据
     * @param data 将被转换的对象
     * @return 转换成功返回BigDecimal类型数据，否则返回NoneType.DECIMAL
     */
    public static BigDecimal toDecimal(Object data) {
        BigDecimal result = NoneTypeUtil.DECIMAL;
        String temp = toString(data);

        try {

            if (!NoneTypeUtil.isNull(temp)) {

                if (temp.indexOf(".") > -1)
                    result = BigDecimal.valueOf(toDouble(temp));
                else
                    result = BigDecimal.valueOf(toLong(temp));
            }

        } catch (Exception e) {
            LOG.error("ClassTypeUtil.toDecimal(Object data)报错,可能包含非数字字符", e);
        }
        return result;
    }

    /**
     * 将指定的对象转换成boolean类型
     * @param data 将被转换的对象
     * @return 转换成功返回boolean类型数据，否则返回NoneType.BOOLEAN
     */
    public static boolean toBoolean(Object data) {
        boolean result = NoneTypeUtil.BOOLEAN;
        String temp = toString(data);

        if (!NoneTypeUtil.isNull(temp)){
            result = Boolean.parseBoolean(temp);
        }

        return result;
    }

    /**
     * 判断指定数据的类型是否为基础类型
     * @param type 将被判断的数据类型
     * @return 如果是基础类型则返回true,否则返回false.
     */
    public static boolean isPrimitive(Class<?> type) {
        boolean result = false;

        if (type.isPrimitive())
            result = true;

        return result;
    }

    /**
     * 判断当前类型是否为常用类型(int\double\Date\String等常用的类型)
     * @param beanType 对象类型
     * @return 如果是常用类型则返回true,否则返回false.
     */
    public static boolean isOrdinary(Class<?> beanType) {
        boolean result = false;

        if (isPrimitive(beanType) || beanType.equals(String.class)
                || beanType.equals(Date.class))
            result = true;

        return result;
    }
}
